#include "base/mempool.h"
#include "base/config.h"

#include <malloc.h>
#include <cstring>

#include <iostream>

#include "base/base_buffer.h"
namespace net_tools::base{

Memorypool* Base_buffer::mempool_ = nullptr;

Base_buffer::Base_buffer(int block_number)
  :write_index_(0),
   read_index_(0),
   buf_size_(block_number * _C::BUFFER_MEMPOOL_BLOCK_SIZE),
   next_(this),
   before_(this)
{
  if(mempool_){
    buf_ = mempool_->Get_memory_locked(block_number);
    if(!buf_){ //内存池空了
      free_ = true;
      buf_ = malloc(buf_size_);
    }else{
      free_ = false;
    }
  }else{
    free_ = true;
    buf_ = malloc(buf_size_);
  }
  if(!buf_) [[unlikely]] {
    std::cout << "内存耗尽" << std::endl;
    exit(0);
  }
};

Base_buffer::~Base_buffer(){
  if(free_){
    free(buf_);
  }else{
    mempool_->Free_memory_locked(buf_);
  }
}

void Base_buffer::Write(void* buf,unsigned int size){
  memcpy(Write_index(),buf,size);
  write_index_ += size;
};

void Base_buffer::Singleton_pool(int mempool_block_size,int mempool_block_number){
  static Memorypool mempool(mempool_block_size,mempool_block_number);
  mempool_ = &mempool;
};

char* Base_buffer::operator[](unsigned int index){
  return reinterpret_cast<char*>(buf_) + read_index_ + index;
};

// self -> other => self -> next -> other
void Base_buffer::Insert_next(Base_buffer* next){
  this->next_->before_ = next;
  next->next_ = this->next_;
  this->next_ = next;
  next->before_ = this;
};

// other -> self => other -> pre -> self
void Base_buffer::Insert_pre(Base_buffer* pre){
  this->before_->next_ = pre;
  pre->before_ = this->before_;
  this->before_ = pre;
  pre->next_ = this;
};

} // net_tools::base